package com.suxin.spring.configuration;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.PriorityOrdered;

/**
 * @author Tang
 * @classname ConfigurationPropertiesBindingPostProcessor
 * @description [  ]
 * @date 2023/3/18 16:53
 */
public class ConfigurationPropertiesBindingPostProcessor implements BeanPostProcessor, PriorityOrdered, ApplicationContextAware, InitializingBean {


    private final static Class<?> BEAN_CLASS = ConfigurationPropertiesBindingPostProcessor.class;
    private final static String BEAN_CLASS_NAME = BEAN_CLASS.getName();

    private ConfigurationPropertiesBinder binder;
    private ApplicationContext applicationContext;

    public static void register(BeanDefinitionRegistry registry) {
        final GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(BEAN_CLASS);
        beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registry.registerBeanDefinition(BEAN_CLASS_NAME, beanDefinition);
        // 注册binder
        ConfigurationPropertiesBinder.register(registry);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public int getOrder() {
        return 50;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        bind(ConfigurationPropertiesBean.get(this.applicationContext, bean, beanName));
        return null;
    }

    private void bind(ConfigurationPropertiesBean configurationPropertiesBean) {
        this.binder.bind(configurationPropertiesBean);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.binder = ConfigurationPropertiesBinder.get(this.applicationContext);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
}
